package com.fix.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.LinkedList;
import java.util.Properties;


/**
 * 自定义连接池
 * @author sanzang
 *
 */
public class DbPool {
	
	private static DbPool pool;    //自己的属性
	private static String driverClass;
	private static String url;
	private static String userName;
	private static String password;  // 连接的属性
	
	private static int initCount=3;  //初始连接
	private static int minCount=3;   //最小连接数
	private static int maxCount=10;   //最大连接数
	private static int count;      // 当前的连接数
	// 用集合存池子
	LinkedList<Connection> conns = new LinkedList<Connection>();
	
	static {
		Properties prop = new Properties();
		InputStream file =DbPool.class.getClassLoader().getResourceAsStream("db.properties");
		try {
			prop.load(file); //读取配置文件
			driverClass=prop.getProperty("jdbc.driverClass");
			url=prop.getProperty("jdbc.url");
			userName=prop.getProperty("jdbc.userName");
			password=prop.getProperty("jdbc.password");
			// 用户不配置，使用默认值
			try {
				initCount=new Integer(prop.getProperty("jdbc.initCount"));
			} catch (Exception e) {}
			try {
				minCount=new Integer(prop.getProperty("jdbc.minCount"));
			} catch (Exception e) {}
			try {
				maxCount=new Integer(prop.getProperty("jdbc.maxCount"));
			} catch (Exception e) {}
			 		
		} catch (IOException e) {
			e.printStackTrace();
		}
	} 
	
	public synchronized static DbPool getPool() {
		if(pool==null) {
			pool = new DbPool();
		}
		return pool;
	}
		
	//构造方法私有
	private DbPool() {
		init();
	}
	
	// 初始化连接池
	private void init() {
		//循环集合里添加连接
		for (int i = 0; i < initCount; i++) {
			boolean ok = conns.add( createConn() );
			if (ok) {
				count++;
			}
		}
		System.out.println("连接池初始化完成，连接数量="+count);
	}
	
	//获取连接的方法
	private Connection createConn() {	
		try {
			Class.forName(driverClass);
			return DriverManager.getConnection(url,userName,password);
		} catch (Exception e) {
			throw new RuntimeException("连接创建失败:"+ e.getMessage());
		}
	}
	
	//增加连接的方法
	private synchronized void autoAdd() {
		//步长为2	
		if(count == maxCount) {
			throw new RuntimeException("连接池满了，不能再增加了");
		}	
		for (int i = 0; i < 2; i++) {
			conns.add(createConn());
			count++;
			if(count == maxCount) {
				break;
			}
		}
	}
	
	
	/**
	 * 获取池中连接
	 */
	public  Connection getConn() {
		// 池子里有没有连接
		if( conns.size() > 0 ) {
			return conns.removeFirst();
		}
		//如果没有了，总连接数没到上线
		if(count < maxCount) {
			autoAdd();
			// 增加完后，递归调用自己
			return getConn();
		}
		//总连接数已经达到上线，我们就等待一会再去获取
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} 
		return getConn();
	}
	
	/**
	 * 连接池自动缩减
	 */
	public synchronized void sub() {
		// 空闲的连接 > 最小连接数
		if( conns.size() > minCount) {
			try {
				Connection conn = conns.removeFirst();
				conn.close();
				conn=null;
				// 连接数 -1 
				count--;
			} catch (Exception e) {
				e.printStackTrace();
			}	
		}
	}
	
	/**
	 * 还回连接
	 */
	public void back(Connection c) {
		conns.add(c);  //加入集合
		// 是否要缩减，优化
		sub();
	}
	
	

}
